package com.youkeda.app.service.impl;

    import com.youkeda.app.dao.PersonalRecordDAO;
    import com.youkeda.app.dataobject.PersonalRecordDO;
    import com.youkeda.app.model.PersonalRecord;
    import com.youkeda.app.model.User;
    import com.youkeda.app.service.PersonalRecordService;
    import com.youkeda.app.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.DefaultTypedTuple;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Service;
    import org.springframework.util.CollectionUtils;

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Set;
    import java.util.stream.Collectors;

/**
 * @author 刘正星
 * @version 1.0.0
 * @ClassName PersonalRecordServiceImpl.java
 * @Description TODO
 * @createTime 2020年09月30日 19:02:00
 */
@Service
public class PersonalRecordServiceImpl implements PersonalRecordService {

    @Autowired
    private PersonalRecordDAO personalRecordDAO;
    @Autowired
    private UserService userService;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public int save(PersonalRecord personalRecord) {
        PersonalRecordDO personalRecordDO = new PersonalRecordDO(personalRecord);


        if (personalRecord.getId() == null) {
            return personalRecordDAO.insert(personalRecordDO);
        }
        //修改redis改用户的缓存积分信息
        redisTemplate.opsForZSet().add("integralRank", personalRecordDO.getUserId(), personalRecord.getPoints());
        return personalRecordDAO.updateByPrimaryKey(personalRecordDO);
    }

    @Override
    public PersonalRecord findByUserId(Long userId) {

        if (userId == null) {
            return null;
        }
        Double score = redisTemplate.opsForZSet().score("integralRank", userId);
        if (score !=null){
            PersonalRecord personalRecord = new PersonalRecord();
                User user = (User)redisTemplate.opsForHash().get("user",userId);
                personalRecord.setPoints(score.intValue());
                personalRecord.setUser(user);
                return personalRecord;
        }else {
            PersonalRecordDO personalRecordDO = personalRecordDAO.selectByPrimaryKey(userId);

            if (personalRecordDO == null) {
                return null;
            }

            PersonalRecord personalRecord = personalRecordDO.convertToModel();

            //组装战绩和用户信息
            if (personalRecord.getUserId() != null) {
                User user = userService.get(personalRecord.getUserId());
                if (user != null) {
                    personalRecord.setUser(user);
                }

            }

            return personalRecord;
        }

    }

    @Override
    public List<PersonalRecord> queryLimit(Long limitNum) {
        List<PersonalRecord> personalRecords = new ArrayList<>();
        //System.out.println("service : " + limitNum);
        //先去redis取数据，如果没有则去数据库查询 0代表从第0条数据开始 n-1代表结束位置

        Set<DefaultTypedTuple> integralRank = (Set<DefaultTypedTuple>) redisTemplate.opsForZSet().reverseRangeWithScores("integralRank", 0, limitNum - 1);
        if (integralRank != null) {
            //去hash查询用户信息
            List<Long> userIds = integralRank.stream().map(defaultTypedTuple -> (Long) defaultTypedTuple.getValue()).collect(Collectors.toList());
            personalRecords = integralRank.stream().map(defaultTypedTuple -> {
                PersonalRecord personalRecord = new PersonalRecord();
                personalRecord.setPoints(defaultTypedTuple.getScore().intValue());
                personalRecord.setUserId((Long) defaultTypedTuple.getValue());
                return personalRecord;
            }).collect(Collectors.toList());
           // List<User> users = redisTemplate.opsForHash().multiGet("integralRankUser", userIds);
           // System.out.println(users.get(0).toString());
           // users.forEach(user -> System.out.println(user.toString()));

            List<User>  users = userService.getByIds(userIds);

            users.forEach(user -> System.out.println(user.toString()));
            //组装信息
            for(PersonalRecord personalRecord:personalRecords){
                for (User user:users){
                    if (user.getId().equals(personalRecord.getUserId())){
                        personalRecord.setUser(user);
                    }
                }
            }

            return personalRecords;
            //为空则去数据库查询
        } else {
            List<PersonalRecordDO> personalRecordDOS = personalRecordDAO.selectAll(limitNum);
            List<Long> userIds = personalRecordDOS.stream().map(PersonalRecordDO::getUserId).collect(Collectors.toList());
            //userIds.forEach(System.out::println);
            List<User> users = userService.getByIds(userIds);
            //组装user 到personalRecords
            personalRecords = personalRecordDOS.stream()
                    .map(personalRecordDO -> {
                        PersonalRecord personalRecord = personalRecordDO.convertToModel();
                        users.forEach(user1 -> {
                            if (personalRecord.getUserId().equals(user1.getId())) {
                                personalRecord.setUser(user1);
                            }
                        });
                        return personalRecord;
                    }).collect(Collectors.toList());

        }

        return personalRecords;

    }

    @Override
    public Long getRankIndex(Long userId) {
        if (userId == null) {
            return null;
        }
        Long rankNum = redisTemplate.opsForZSet().rank("integralRank", userId);
        if (rankNum !=null){
            return rankNum;
        }
        Long rowNum = personalRecordDAO.selectRankIndex(userId);
       // System.out.println("rowNum = [" + rowNum + "]");
        return rowNum;
    }

    @Override
    public Integer delete(Long userId) {
        if (userId == null) {
            return null;
        }
        Integer deleteNum = personalRecordDAO.delete(userId);
        if (deleteNum < 1) {
            return null;
        }
        return deleteNum;
    }
}
